<?php
namespace Sharks\Core\Persistence\QueryBuilder;

use PDO;
use Sharks\Core\Persistence\Db;
use Sharks\Core\Support\Base\Precondition;
use Sharks\Core\Support\Base\Str;

/**
 * 原生SQL查询
 * <pre>
 *      $sql = "select * from foo"
 *      $query = new RawSqlSelectQuery($sql);
 *      $query->lists();
 *
 *      $sql = "selct * from foo where bar = :bar";
 *      $query = new RawSqlSelectQuery($sql);
 *      $query->bind('bar', 1);
 *      $query->lists();
 * </pre>
 */
class RawSqlSelectQuery extends AbstractSelectQuery {

    protected $sql;
    protected $stmt;
    protected $identifier;

    public function __construct($sql, $identifier) {
        Precondition::check(Str::startsWith($sql, 'select') || Str::startsWith($sql, 'SELECT'), "非SELECT查询");
        $this->sql = $sql;
        $this->identifier = $identifier;
    }

    /**
     * 绑定SQL查询参数
     * @param $name 参数名称
     * @param $value 参数值
     */
    public function bind($name, $value) {
        if (is_null($this->stmt)) {
            $this->stmt = Db::connector()->prepare($this->sql);
        }
        $this->stmt->bindValue(":$name", $value);
        return $this;
    }

    /**
     * 列表数据
     * @return array|bool
     * @throws \Sharks\Core\Exception\DatabaseException
     */
    public function lists() {
        if (is_null($this->stmt)) {
            $this->stmt = Db::connector()->query($this->sql);
        }
        else {
            $this->stmt->execute();
        }
        $rows = $this->stmt->fetchAll(PDO::FETCH_ASSOC);
        $this->checkError($this->stmt);
        return false == $rows ? array() : $this->buildObjs($rows);
    }

    /**
     * 单一数据
     * @return bool|null|\Sharks\Core\Persistence\DbRecord
     * @throws \Sharks\Core\Exception\DatabaseException
     */
    public function only() {
        if (is_null($this->stmt)) {
            $this->stmt = Db::connector()->query($this->sql);
        }
        else {
            $this->stmt->execute();
        }
        $row = $this->stmt->fetch(PDO::FETCH_ASSOC);
        $this->checkError($this->stmt);

        return false == $row ? null : $this->buildObj($row);
    }

    public function pick() {
        if (is_null($this->stmt)) {
            $this->stmt = Db::connector()->query($this->sql);
        }
        else {
            $this->stmt->execute();
        }
        $row = $this->stmt->fetch(PDO::FETCH_ASSOC);
        $this->checkError($this->stmt);
        return false == $row ? array() : $row;
    }
}